package com.kamikaze.docidset.impl;

import java.io.IOException;
import java.io.Serializable;

import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.DocIdSetIterator;


public class NotDocIdSet extends ImmutableDocSet implements Serializable {

  private static final long serialVersionUID = 1L;

  private DocIdSet innerSet = null;

  private int max = -1;

 public NotDocIdSet(DocIdSet docSet, int maxVal) {
    innerSet = docSet;
    max = maxVal;
   
  }

  class NotDocIdSetIterator extends DocIdSetIterator {
    int lastReturn = -1;
    private DocIdSetIterator it1 = null;

    NotDocIdSetIterator() {
      initialize();
    }

    private void initialize() {
      it1 = innerSet.iterator();

      try {
        if (!it1.next()) it1 = null;
      } catch (IOException e) {
        e.printStackTrace();
      }
    }

    @Override
    public int doc() {
      return lastReturn;
    }

    @Override
    public boolean next() throws IOException {
      return skipTo(lastReturn + 1);
    }

    @Override
    public boolean skipTo(int target) throws IOException {
      
      //if (target <= lastReturn) target = lastReturn + 1;
      if (target <= lastReturn) return true;
      
      lastReturn = target;
      
      if (lastReturn >= max) return false;

      if (it1 != null && it1.doc() < lastReturn) {
        if (!it1.skipTo(lastReturn)) {
          it1 = null;
        }
      }
      
      while (it1 != null && it1.doc() == lastReturn) {
        lastReturn++;
        if (lastReturn >= max) return false;
        if (!it1.skipTo(lastReturn)) {
          it1 = null;
        }
      }
      return true;
    }
  }

  @Override
  public DocIdSetIterator iterator() {
    return new NotDocIdSetIterator();
  }
  
  /**
   * Find existence in the set with index
   * 
   * NOTE :  Expensive call. Avoid.
   * @return
   */
  @Override
  public int findWithIndex(int val)
  {
    DocIdSetIterator finder = new NotDocIdSetIterator();
    int cursor = -1;
    try {
      while(finder.next())
      {
        if(finder.doc() > val)
          return -1;
        else if(finder.doc() == val )
          return ++cursor;
        else 
          ++cursor;
        
      
      }
    } catch (IOException e) {
      return -1;
    }
    return -1;
  }
  

}
